Skip to content

Cayo oliveira/cu 86af019hb/5 backend envio de mensagens baileys#227

Merged
gabrieljablonski merged 77 commits intoCayo-Oliveira/CU-86af00yvg/2-Backend-Models-Main-PRfrom
Cayo-Oliveira/CU-86af019hb/5-Backend-Envio-de-mensagens-Baileys
Feb 27, 2026
Merged

Cayo oliveira/cu 86af019hb/5 backend envio de mensagens baileys#227
gabrieljablonski merged 77 commits intoCayo-Oliveira/CU-86af00yvg/2-Backend-Models-Main-PRfrom
Cayo-Oliveira/CU-86af019hb/5-Backend-Envio-de-mensagens-Baileys

Conversation

@CayoPOliveira
Copy link

@CayoPOliveira CayoPOliveira commented Feb 27, 2026

WhatsApp Baileys: Message sending enhancements for group conversations & receipt updates

Summary

This PR builds on top of the group management branch by adding proper message key handling for group conversations and implementing message receipt status updates from Baileys.

Changes

Message key participant handling for groups

  • Extracted a reusable message_key_for helper in WhatsappBaileysService that builds WhatsApp message keys with the participant field for incoming messages in group conversations (@g.us JIDs). This ensures Baileys correctly identifies message authors when performing operations like quoting, reacting, reading, deleting, and editing messages in groups.
  • Applies to: read_messages, unread_message, received_messages, send_message (quoted replies & reactions), delete_message, and edit_message.

Message receipt update handler

  • Added Whatsapp::BaileysHandlers::MessageReceiptUpdate module to handle message-receipt.update events from Baileys.
  • Supports status transitions: sent → delivered (on receiptTimestamp) and sent/delivered → read (on readTimestamp), with guards preventing status downgrades.
  • Updates agent_last_seen_at and assignee_last_seen_at on the conversation when an incoming message is marked as read.
  • Uses with_baileys_channel_lock_on_outgoing_message for outgoing messages to avoid race conditions with SendOnWhatsappService.

Minor refactor

  • Changed update_columns to save! in MessagesUpdate#update_last_seen_at for consistency with the new receipt handler.

Tests

  • Added comprehensive specs for MessageReceiptUpdate (status transitions, downgrade prevention, conversation timestamp updates).
  • Added specs for group participant handling across all affected WhatsappBaileysService methods (send_message, read_messages, unread_message, received_messages, delete_message, edit_message).
  • Simplified GroupMembersController specs to remove service mocking.

This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Message status now correctly transitions between sent, delivered, and read states based on receipt updates.
    • Conversation timestamps automatically update when messages are read by recipients.
  • Tests

    • Comprehensive test coverage added for message receipt handling, status transitions, and group message operations.

…eation logic for baileys single contact conversation
…to Cayo-Oliveira/CU-86af01932/4-Backend-Gerenciamento-dos-grupos
@CayoPOliveira CayoPOliveira self-assigned this Feb 27, 2026
@CayoPOliveira CayoPOliveira added enhancement New feature or request review needed labels Feb 27, 2026
@gabrieljablonski
Copy link
Member

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request introduces WhatsApp message receipt update handling through a new handler module that processes receipt status changes (sent → delivered → read), enforces valid status transitions, and updates conversation agent/assignee timestamps. Additionally, the WhatsApp Baileys provider undergoes refactoring to centralize message key generation, and comprehensive test coverage is added for receipt transitions and group message scenarios.

Changes

Cohort / File(s) Summary
Documentation
.claude/skills/rspec-tests/SKILL.md
New RSpec testing guidelines documenting core principles, project conventions, and structure examples with code samples for Service and Request specs.
Message Receipt Handler
app/services/whatsapp/baileys_handlers/message_receipt_update.rb
New module providing receipt update processing with status-transition validation, conversation timestamp updates (agent/assignee last-seen), and helpers for receipt status inference and transition rules enforcement.
Service Integration
app/services/whatsapp/incoming_message_baileys_service.rb
Includes MessageReceiptUpdate handler to wire receipt update processing into the service.
Provider Message Key Refactoring
app/services/whatsapp/providers/whatsapp_baileys_service.rb
Replaces scattered key construction with centralized helpers: message_key_for() and group_participant_jid() to unify message identifier generation across read, unread, delete, edit, react, and receipt operations.
Message Update Persistence
app/services/whatsapp/baileys_handlers/messages_update.rb
Changes message timestamp persistence from update_columns (validation-skip) to direct attribute assignment and save!, enabling validation and callbacks during persistence.
Receipt Status Transition Tests
spec/services/whatsapp/incoming_message_baileys_service_spec.rb
Adds comprehensive test coverage for message-receipt.update events, validating status transitions (sent→delivered→read), downgrades prevention, and conversation timestamp updates on read receipts.
Group Message Tests
spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb
Adds extensive tests for group message handling covering send, read, unread, receive, react, delete, and edit operations with participant JID inclusion validation across message directions.

Sequence Diagram

sequenceDiagram
    actor Baileys as WhatsApp Baileys API
    participant Service as IncomingMessageBaileysService
    participant Handler as MessageReceiptUpdate Handler
    participant Message as Message Model
    participant Conversation as Conversation Model

    Baileys->>Service: message-receipt.update event
    Service->>Handler: process_message_receipt_update(receipts)
    Handler->>Handler: iterate receipts
    Handler->>Message: find message by key
    Message-->>Handler: message found
    Handler->>Handler: extract status (read/delivered)
    Handler->>Handler: validate transition allowed?
    alt Transition Valid
        Handler->>Message: update status
        Message->>Message: save!
        Message-->>Handler: ✓ saved
        alt Incoming Message & Read Status
            Handler->>Conversation: update agent_last_seen_at
            Handler->>Conversation: update assignee_last_seen_at
            Conversation->>Conversation: save!
            Conversation-->>Handler: ✓ timestamps updated
        end
    else Transition Invalid
        Handler->>Handler: skip (no-op)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • gabrieljablonski

Poem

🐰 Read receipts bounce from sent to read with glee,
Keys now unified—consolidated, you see!
Timestamps dance through every state transition,
Guards enforce each valid permission! ✨
Baileys handlers blend in sweet harmony,
A message-receipt ballet of machinery!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is overly vague and uses non-descriptive language; it references a task ID and is in Portuguese, lacking clarity about the main changes (message receipt handling and group participant support for Baileys integration). Revise the title to clearly describe the primary change in English, such as 'Add message receipt handling and group participant support for Baileys WhatsApp integration' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch Cayo-Oliveira/CU-86af019hb/5-Backend-Envio-de-mensagens-Baileys

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@CayoPOliveira
Copy link
Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enhances the WhatsApp Baileys integration by correctly building message keys for group operations (including participant for incoming group messages) and by handling Baileys receipt events to update Chatwoot message delivery/read statuses.

Changes:

  • Added a reusable message_key_for helper to include participant for incoming group message keys across multiple Baileys API operations.
  • Added a new Baileys handler for message-receipt.update to transition message statuses (sent → delivered → read) and update conversation last-seen timestamps.
  • Refactored last-seen updates in MessagesUpdate to use save! (instead of update_columns) for consistency with the new handler.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb Adds specs ensuring group message keys include participant only when required (incoming group messages).
spec/services/whatsapp/incoming_message_baileys_service_spec.rb Adds specs for message-receipt.update status transitions and conversation timestamp updates.
app/services/whatsapp/providers/whatsapp_baileys_service.rb Introduces message_key_for + group participant handling and applies it across relevant methods.
app/services/whatsapp/incoming_message_baileys_service.rb Wires the new MessageReceiptUpdate handler into the Baileys incoming service.
app/services/whatsapp/baileys_handlers/messages_update.rb Changes conversation last-seen updates from update_columns to save!.
app/services/whatsapp/baileys_handlers/message_receipt_update.rb New handler for Baileys receipt updates and conversation last-seen updates.
.claude/skills/rspec-tests/SKILL.md Adds project guidance for writing/maintaining RSpec tests.
Comments suppressed due to low confidence (3)

app/services/whatsapp/baileys_handlers/messages_update.rb:67

  • update_last_seen_at now uses save!, which will update updated_at and run before_save/after_update_commit callbacks on Conversation. Elsewhere (e.g. ConversationsController) agent_last_seen_at updates intentionally use update_columns to avoid these side effects. Consider switching back to update_columns (with the existing rubocop disable) so receipt/read processing doesn’t create extra DB churn or trigger callbacks.
    conversation.agent_last_seen_at = Time.current
    conversation.assignee_last_seen_at = Time.current if conversation.assignee_id.present?
    conversation.save!

app/services/whatsapp/baileys_handlers/message_receipt_update.rb:28

  • update_last_seen_at_from_receipt is only called after receipt_status_transition_allowed?. Because that method returns false when the message is already read, duplicate/late readTimestamp receipts will never update conversation.agent_last_seen_at/assignee_last_seen_at. In MessagesUpdate, last-seen timestamps are updated before the transition guard, so they still advance even when status doesn’t change. Consider updating last-seen timestamps based on the receipt payload before/independent of the status-transition check (while still preventing status downgrades).
  def handle_receipt_update
    return unless find_message_by_source_id(raw_message_id)

    new_status = receipt_status
    return if new_status.nil?
    return unless receipt_status_transition_allowed?(new_status)

    update_last_seen_at_from_receipt if incoming? && new_status == 'read'
    @message.update!(status: new_status)

app/services/whatsapp/baileys_handlers/message_receipt_update.rb:50

  • update_last_seen_at_from_receipt uses conversation.save!, which will touch updated_at and run Conversation callbacks on every read receipt. Other parts of the codebase update last-seen fields via update_columns to avoid callbacks/timestamp churn. Consider using update_columns(agent_last_seen_at: ..., assignee_last_seen_at: ...) here as well (with the rubocop disable) to keep receipt processing lightweight.
  def update_last_seen_at_from_receipt
    conversation = @message.conversation
    conversation.agent_last_seen_at = Time.current
    conversation.assignee_last_seen_at = Time.current if conversation.assignee_id.present?
    conversation.save!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/services/whatsapp/baileys_handlers/message_receipt_update.rb (1)

46-50: Consider extracting shared last-seen updater to avoid logic drift.

This block duplicates update_last_seen_at from app/services/whatsapp/baileys_handlers/messages_update.rb and can diverge over time.

♻️ Suggested refactor
# app/services/whatsapp/baileys_handlers/helpers.rb (or a shared concern)
+def update_conversation_last_seen!(conversation)
+  now = Time.current
+  conversation.agent_last_seen_at = now
+  conversation.assignee_last_seen_at = now if conversation.assignee_id.present?
+  conversation.save!
+end
# app/services/whatsapp/baileys_handlers/message_receipt_update.rb
 def update_last_seen_at_from_receipt
-  conversation = `@message.conversation`
-  conversation.agent_last_seen_at = Time.current
-  conversation.assignee_last_seen_at = Time.current if conversation.assignee_id.present?
-  conversation.save!
+  update_conversation_last_seen!(`@message.conversation`)
 end
# app/services/whatsapp/baileys_handlers/messages_update.rb
 def update_last_seen_at
-  conversation = `@message.conversation`
-  conversation.agent_last_seen_at = Time.current
-  conversation.assignee_last_seen_at = Time.current if conversation.assignee_id.present?
-  conversation.save!
+  update_conversation_last_seen!(`@message.conversation`)
 end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/services/whatsapp/baileys_handlers/message_receipt_update.rb` around
lines 46 - 50, The two handlers duplicate last-seen update logic
(update_last_seen_at_from_receipt in
app/services/whatsapp/baileys_handlers/message_receipt_update.rb and
update_last_seen_at in
app/services/whatsapp/baileys_handlers/messages_update.rb); extract the shared
behavior into a single helper method (e.g., Conversation#touch_last_seen!, or a
small module/class LastSeenUpdater.call(conversation)) that sets
agent_last_seen_at = Time.current and only sets assignee_last_seen_at when
conversation.assignee_id.present?, then replace both
update_last_seen_at_from_receipt and update_last_seen_at to call that new
helper; ensure you preserve bang-save semantics (save! or equivalent) and
run/update tests that reference either original methods.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/services/whatsapp/baileys_handlers/message_receipt_update.rb`:
- Around line 46-50: The two handlers duplicate last-seen update logic
(update_last_seen_at_from_receipt in
app/services/whatsapp/baileys_handlers/message_receipt_update.rb and
update_last_seen_at in
app/services/whatsapp/baileys_handlers/messages_update.rb); extract the shared
behavior into a single helper method (e.g., Conversation#touch_last_seen!, or a
small module/class LastSeenUpdater.call(conversation)) that sets
agent_last_seen_at = Time.current and only sets assignee_last_seen_at when
conversation.assignee_id.present?, then replace both
update_last_seen_at_from_receipt and update_last_seen_at to call that new
helper; ensure you preserve bang-save semantics (save! or equivalent) and
run/update tests that reference either original methods.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 049239d and efd953e.

📒 Files selected for processing (7)
  • .claude/skills/rspec-tests/SKILL.md
  • app/services/whatsapp/baileys_handlers/message_receipt_update.rb
  • app/services/whatsapp/baileys_handlers/messages_update.rb
  • app/services/whatsapp/incoming_message_baileys_service.rb
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb
  • spec/services/whatsapp/incoming_message_baileys_service_spec.rb
  • spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb

Base automatically changed from Cayo-Oliveira/CU-86af01932/4-Backend-Gerenciamento-dos-grupos to Cayo-Oliveira/CU-86af00yvg/2-Backend-Models-Main-PR February 27, 2026 13:25
@gabrieljablonski
Copy link
Member

Task linked: CU-86af00yvg 2 - Backend - Models (Main PR)

Copy link
Member

@gabrieljablonski gabrieljablonski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-(review needed) +(approved for merge)

@gabrieljablonski reviewed 56 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on CayoPOliveira).

…to Cayo-Oliveira/CU-86af019hb/5-Backend-Envio-de-mensagens-Baileys
@gabrieljablonski gabrieljablonski merged commit 569c780 into Cayo-Oliveira/CU-86af00yvg/2-Backend-Models-Main-PR Feb 27, 2026
1 of 2 checks passed
@gabrieljablonski gabrieljablonski deleted the Cayo-Oliveira/CU-86af019hb/5-Backend-Envio-de-mensagens-Baileys branch February 27, 2026 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved for merge enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants